package com.auxgroup.smarthome.service;

import com.alibaba.fastjson.JSONObject;
import com.auxgroup.bridge.app.inner.vo.DeviceInfoNewVo;
import com.auxgroup.bridge.app.inner.vo.DeviceInfoVo;
import com.auxgroup.smarthome.appconst.BusinessConstant;
import com.auxgroup.smarthome.constant.cache.CachedConsant;
import com.auxgroup.smarthome.enterprise.service.DeviceManageService;
import com.auxgroup.smarthome.enterpriseapi.requestbody.SearchDeviceWiFiBody;
import com.auxgroup.smarthome.enterpriseapi.responsebody.WIFIDeviceList;
import com.auxgroup.smarthome.entity.AppHomeDistanceEntity;
import com.auxgroup.smarthome.mqtt.AuxMqttClient;
import com.auxgroup.smarthome.redis.config.ObjectRedis;
import com.auxgroup.smarthome.repo.AppHomeDistanceRepo;
import com.auxgroup.smarthome.service.inner.DeviceInfoInnerService;
import com.auxgroup.smarthome.utils.DistanceCalculateUtil;
import com.auxgroup.smarthome.utils.common.LOG;
import com.auxgroup.smarthome.vo.AppHomeDistanceRedisVo;
import com.auxgroup.smarthome.web.ApiResponse;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.fusesource.mqtt.client.Callback;
import org.fusesource.mqtt.client.Message;
import org.fusesource.mqtt.client.QoS;
import org.fusesource.mqtt.client.Topic;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

/**
 * 离家回家模式业务类
 * Created by lixiaoxiao on 17-8-14.
 */
@Slf4j
@Component
public class HomeDistanceMqttService {

    @Autowired
    private AppHomeDistanceRepo appHomeDistanceRepo;

    @Autowired
    private DeviceInfoInnerService deviceInfoInnerService;

    @Autowired
    private ObjectRedis objectRedis;

    @Autowired
    private DeviceManageService deviceManageService;

    @Autowired
    private AuxMqttClient auxMqttClient;

    /**
     * 初始化mqtt连接
     */
    public void init() {
        Topic[] topics = {new Topic(CachedConsant.HOME_DISTANCE_CACHED_PREFIX, QoS.AT_LEAST_ONCE)};
        auxMqttClient.setTopics(Arrays.asList(topics));
        auxMqttClient.connect();
        auxMqttClient.receive(new ReciveCallback());

    }

    public void remoteControlDevice(String deviceId, Map<String, String> controlMap, String distanceId, int status) {
        ApiResponse<DeviceInfoNewVo> deviceInfoNewVoApiResponse =
                deviceInfoInnerService.getDeviceNewInfoByDeviceId(deviceId);
        DeviceInfoNewVo deviceInfoNewVo = deviceInfoNewVoApiResponse.getData();
        if (deviceInfoNewVo.isNewDevice()) {
            //下发前再判断是否已经执行过 add by lixiaoxiao 20180130
            AppHomeDistanceEntity appHomeDistanceEntity = appHomeDistanceRepo.findByDistanceId(distanceId);
            if (null != appHomeDistanceEntity && status != appHomeDistanceEntity.getModeLaunch()) {
                deviceManageService.commonRemoteControlDevice(
                        deviceInfoNewVo.getProductKey(), deviceInfoNewVo.getDid(), controlMap);
            }

        }
    }

    public DeviceInfoVo getDeviceInfo(String deviceId) {
        String rediskey = CachedConsant.HOME_DISTANCE_CACHED_PREFIX + deviceId;
        DeviceInfoVo deviceInfoVo = objectRedis.get(rediskey, DeviceInfoVo.class);
        if (deviceInfoVo == null) {
            ApiResponse<DeviceInfoVo> apiResponse = deviceInfoInnerService.getDeviceInfo(deviceId);
            objectRedis.add(rediskey, apiResponse.getData());
        }
        return deviceInfoVo;
    }

    public WIFIDeviceList.WIFIDeviceInfo getDeviceDetail(String productKey, String did) {
        String rediskey = CachedConsant.HOME_DISTANCE_CACHED_PREFIX + productKey + "/" + did;
        WIFIDeviceList.WIFIDeviceInfo wifiDeviceInfo = objectRedis.get(rediskey, WIFIDeviceList.WIFIDeviceInfo.class);
        if (wifiDeviceInfo == null) {
            SearchDeviceWiFiBody body = new SearchDeviceWiFiBody();
            body.setType("did");
            body.setVal(did);
            ApiResponse<WIFIDeviceList> apiResponse = deviceManageService.searchWiFiDevice(productKey, body);
            if (apiResponse.getCode() != 200) {
                return null;
            }
            List<WIFIDeviceList.WIFIDeviceInfo> wifiDeviceInfos = apiResponse.getData().getObjects();
            if (wifiDeviceInfos.size() <= 0) {
                return null;

            }
            wifiDeviceInfo = wifiDeviceInfos.get(0);
            objectRedis.add(rediskey, wifiDeviceInfo);
        }
        return wifiDeviceInfo;
    }

    /**
     * 设置用户-设备的离家回家缓存
     *
     * @param appHomeDistanceEntity 离家回家实体类
     */
    public void saveUserDeviceHomeDistanceCache(AppHomeDistanceEntity appHomeDistanceEntity) {
        String redisKey = CachedConsant.HOME_DISTANCE_CACHED_PREFIX + appHomeDistanceEntity.getuId() + "/" + appHomeDistanceEntity.getDeviceId();
        if (appHomeDistanceEntity.getOn())
            objectRedis.add(redisKey, appHomeDistanceEntity);
        else
            objectRedis.delete(redisKey);
    }


    /**
     * 根据用户id获取该用户开启离家回家的设备列表
     *
     * @param uid 用户id
     * @return
     */
    public List<AppHomeDistanceEntity> getUserDeviceListByUId(String uid) {
        String redisKeyPatter = CachedConsant.HOME_DISTANCE_CACHED_PREFIX + uid + "/*";
        List<AppHomeDistanceEntity> appHomeDistanceEntityList = objectRedis.getAllObjects(redisKeyPatter, AppHomeDistanceEntity.class);
        if (null == appHomeDistanceEntityList) {
            appHomeDistanceEntityList = appHomeDistanceRepo.findByUId(uid);
            for (AppHomeDistanceEntity appHomeDistanceEntity : appHomeDistanceEntityList) {
                String redisKey = CachedConsant.HOME_DISTANCE_CACHED_PREFIX + uid + "/" + appHomeDistanceEntity.getDeviceId();
                objectRedis.add(redisKey, appHomeDistanceEntity);
            }
        }
        return appHomeDistanceEntityList;
    }

    /**
     * 接收消息回调
     */
    class ReciveCallback implements Callback<Message> {

        @Override
        public void onSuccess(Message value) {
            //获取订阅的消息内容
            byte[] payload = value.getPayload();
            JSONObject jsonObject = JSONObject.parseObject(new String(payload));
            /**
             * 业务逻辑
             * 从app端获取经纬度,对比设备所在的经纬度,比较距离长短,再去拿设置距离比较
             * 当前距离大于设置距离并且持续一分钟关闭空调,反之则开启空调
             */
            String uid = jsonObject.getString("uid");
            String latFromStr = jsonObject.getString("lat");
            String lngFromStr = jsonObject.getString("lng");
            Long createAt = jsonObject.getLong("time");
            log.debug("MQTT接收到用户:" + uid + "发送的经纬度信息,纬度:" + latFromStr + ",经度:" + lngFromStr);
            //根据用户id获取该用户开启离家回家的设备列表(先从redis取数据，如果没有就去数据库取) 修改人：吴建龙 修改时间：2018-05-16
            List<AppHomeDistanceEntity> appHomeDistanceEntityList = getUserDeviceListByUId(uid);
            //循环当前用户下的所有开启离家回家模式的设备
            for (Iterator iter = appHomeDistanceEntityList.iterator(); iter.hasNext(); ) {
                AppHomeDistanceEntity appHomeDistanceEntity = (AppHomeDistanceEntity) iter.next();
                String deviceId = appHomeDistanceEntity.getDeviceId();
                String redisKey = CachedConsant.HOME_DISTANCE_CACHED_PREFIX + deviceId + "/" + uid;
                if (null == deviceId) continue;
                String latEndStr = "";
                String lngEndStr = "";
                DeviceInfoVo deviceInfoVo = getDeviceInfo(deviceId);
                if (null == deviceInfoVo) continue;
                if (StringUtils.isNotBlank(deviceInfoVo.getLatitude()) && StringUtils.isNotBlank(deviceInfoVo.getLongitude())) {
                    latEndStr = deviceInfoVo.getLatitude();
                    lngEndStr = deviceInfoVo.getLongitude();
                } else {
                    WIFIDeviceList.WIFIDeviceInfo device = getDeviceDetail(deviceInfoVo.getProductKey(), deviceInfoVo.getDid());
                    latEndStr = device.getLatitude();
                    lngEndStr = device.getLongitude();
                }
                double distance = DistanceCalculateUtil.getDistance(latFromStr, lngFromStr, latEndStr, lngEndStr);
                AppHomeDistanceRedisVo appHomeDistanceVo = objectRedis.get(redisKey, AppHomeDistanceRedisVo.class);
                if (appHomeDistanceVo != null) {
                    //比较上一次的位置和时间
                    if (distance < appHomeDistanceEntity.getDistance()
                            && appHomeDistanceVo.getDistance() < appHomeDistanceEntity.getDistance()
                        /*&& ((createAt - appHomeDistanceVo.getCreatedAt()) / 1000 >= 60)*/) {
                        if (appHomeDistanceEntity.getModeLaunch() != BusinessConstant.APP_HOME_DISTANCE_BACK.getValue()) {
                            Map<String, String> controlMap = new HashMap<>();
                            controlMap.put("on_off", "1");
                            // modify by qiuhua: 开机指令显示温度为整数，关闭0.5度温度设置
                            controlMap.put("half", "0");
                            remoteControlDevice(deviceId, controlMap, appHomeDistanceEntity.getDistanceId(), BusinessConstant.APP_HOME_DISTANCE_BACK.getValue());
                            appHomeDistanceEntity.setModeLaunch(
                                    BusinessConstant.APP_HOME_DISTANCE_BACK.getValue());
                            AppHomeDistanceEntity appHomeDistanceEntity1 = appHomeDistanceRepo.save(appHomeDistanceEntity);
                            //设置用户-设备的离家回家缓存 修改人：吴建龙 修改时间：2018-05-16
                            saveUserDeviceHomeDistanceCache(appHomeDistanceEntity1);
                            LOG.info(this, "设备:" + deviceId + " 下发开机指令");
                            objectRedis.delete(redisKey);
                            continue;
                        }
                    } else if (distance > appHomeDistanceEntity.getDistance()
                            && appHomeDistanceVo.getDistance() > appHomeDistanceEntity.getDistance()
                        /*&& ((createAt - appHomeDistanceVo.getCreatedAt()) / 1000 >= 60)*/) {
                        if (appHomeDistanceEntity.getModeLaunch() != BusinessConstant.APP_HOME_DISTANCE_AWAY.getValue()) {
                            LOG.info(this, "设备:" + deviceId + " 下发关机指令");
                            Map<String, String> controlMap = new HashMap<>();
                            controlMap.put("on_off", "0");
                            remoteControlDevice(deviceId, controlMap, appHomeDistanceEntity.getDistanceId(), BusinessConstant.APP_HOME_DISTANCE_AWAY.getValue());
                            appHomeDistanceEntity.setModeLaunch(
                                    BusinessConstant.APP_HOME_DISTANCE_AWAY.getValue());
                            AppHomeDistanceEntity appHomeDistanceEntity1 = appHomeDistanceRepo.save(appHomeDistanceEntity);
                            //设置用户-设备的离家回家缓存 修改人：吴建龙 修改时间：2018-05-16
                            saveUserDeviceHomeDistanceCache(appHomeDistanceEntity1);
                            objectRedis.delete(redisKey);
                            continue;
                        }
                    }
                }
                objectRedis.add(redisKey, new AppHomeDistanceRedisVo(distance, createAt));
            }
        }

        @Override
        public void onFailure(Throwable value) {
            log.debug("错误", value);
        }
    }
}
